﻿/*
	Copyright © Bogdan Kobets 2011
	http://ElasticLogic.com
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using ElasticLogic.TagsMarker.Concepts;

namespace ElasticLogic.TagsMarker.Filter
{

	public abstract class AndOr : FilterRule, IEnumerable<FilterRule>
	{
		private FilterRule[] rules;

		public int Count
		{
			get { return rules.Length; }
		}

		public override string Expression
		{
			get { return GetExpression(); }
		}

		protected abstract string RuleName { get; }

		public AndOr(FilterMode mode, params FilterRule[] rules)
			: base(mode)
		{
			this.rules = rules;
		}

		public AndOr(FilterMode mode, params Label[] labels)
			: base(mode)
		{
			int count = labels.Length;
			this.rules = new FilterRule[count];

			for (int i = 0; i < count; i++)
			{
				this.rules[i] = new NOOP(labels[i]);
			}
		}

		public void Add(FilterRule rule)
		{
			FilterRule[] copy = new FilterRule[Count + 1];

			Array.Copy(this.rules, copy, Count);
			copy[Count] = rule;

			this.rules = copy;
		}

		public void Add(Label label)
		{
			this.Add(new NOOP(label));
		}

		public void Clear()
		{
			this.rules = new FilterRule[0];
		}

		public IEnumerator<FilterRule> GetEnumerator()
		{
			foreach (FilterRule rule in this.rules)
			{
				yield return rule;
			}
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.rules.GetEnumerator();
		}

		internal override void ResetSatisfy()
		{
			foreach (FilterRule rule in this.rules)
				rule.ResetSatisfy();

			base.Satisfy = null;
		}

		private string GetExpression()
		{
			StringBuilder text = new StringBuilder('(');

			for (int i = 0; i < Count; i++)
			{
				if (i > 0)
					text.Append(' ').Append(RuleName).Append(' ');

				text.Append(rules[i].Expression);
			}

			text.Append(')');
			return text.ToString();
		}

	}

}
